from model.user import UserDao
from lib.validator import Validator
from lib.form import Form

from flask import request
from flask_login import login_user
import time

class UserService():
    def __init__(self):
        """Arguments:
            name -- string type
            item_id -- BSON ObjectId type
        """
        self.dao = UserDao()
    
    def login(self, account, password, remember_me=False):
        """
        Arguments:
            account: string type, can be username or email address
            password: string type
        Return 
            True if the log in attempt succeeds, otherwise False
        """
        user = self.dao.find_one({'email':account, 'password':password})
        if user is None:
            user = self.dao.find_one({'username':account, 'password':password})
            if user is None:
                return False
            else:
                return login_user(user, remember=remember_me)
        else:
            return login_user(user, remember=remember_me)
            
    def signup(self, form):
        """
        Return:
            The '_id' value of to_save or [None] if manipulate is False and to_save has no _id field.
        """
        if form.errors == []:
            return self.dao.save({'username':form.username,
                         'password':form.password,
                         'email':form.email,
                         'role':0, # Normal user
                         'phone':form.phone,
                         'description':form.description,
                         'created':time.time()}) 
        return None




class UserValidator(Validator):
    def __init__(self):
        Validator.__init__(self)
              
        self.rules = {'username': { 
                                'required' : [None, True],
                                'maxlength':[None, 32]},
                      'password':{'required' : [None, True],
                                  'minlength':[None, 8],
                                  'maxlength':[None, 32]
                               },
                      'email': { 
                                'required' : [None, True],
                                'maxlength':[None, 64],
                                'unique' : [self.unique, 'email', 'This email exists, please try another.']
                                }
        }

    def unique(self, val, field_name):
        _dao = UserDao()
        ret = _dao.find_one({field_name:val})
        return ret is None
    
    
class UserForm(Form):
    """ Submit user form
    """
    def __init__(self):
        """Only accept POST request
        """
        Form.__init__(self)
        self.validator = UserValidator()
        
        if self.is_submitted():
            inputs = self.get_raw_inputs()
            self.errors = self.validator.validate(inputs)
            if self.errors == []:
                self.username = self.request.values.get('username')
                self.password = self.request.values.get('password')
                self.email = self.request.values.get('email')
                self.role = 1 # Normal user
                self.phone = self.request.values.get('phone')
                self.description = None
                
    def has_error(self):
        return self.errors == []
    

class LoginValidator(Validator):
    def __init__(self, account):
        self.account = account
        
        Validator.__init__(self)
        
        self.dao = UserDao()
        self.rules = {'account': { 
                                'account_valid' : [self.account_valid, 'email', 'The account does not exist.']
                                },
                      'password':{
                                'password_valid' : [self.password_valid, 'password', 'Wrong password']
                               }
                    }

    def account_valid(self, val, field_name):
        _dao = UserDao()
        user = _dao.find_one({'email':val})
        if user is None:
            user = _dao.find_one({'username':val})
            return user is not None
        else:
            return True

    def password_valid(self, val, field_name):
        account = self.account
        
        user = self.dao.find_one({'email':account})
        if user is None:
            user = self.dao.find_one({'username':account})
            if user is None:
                return False
            else:
                return user.password == val
        else:
            return user.password == val
       
class LoginForm(Form):
    def __init__(self):
        '''Only accept POST request
        Note: account can be username or email address
        '''
        Form.__init__(self)
        account = request.values.get('account')
        
        self.validator = LoginValidator(account)
        
        if self.is_submitted():
            inputs = self.get_raw_inputs()
            self.errors = self.validator.validate(inputs)
            if self.errors == []:
                # If get fail, return None
                self.account = self.request.values.get('account')
                self.password = self.request.values.get('password')
                if self.request.form.getlist('remember-me') == []:
                    self.remember_me = False
                else:
                    self.remember_me = True
                
    
    def has_error(self):
        return self.errors == []
